/**
 * Class: ChainLink
 *
 * Purpose: A link in a chain
 *
 * Created: Feb 13, 2010 @ 10:06:41 AM
 * @author Ken Scott
 */
package org.openfantasia.ps.particle;

import org.openfantasia.util.math.DPoint3;

public class ChainLink extends Particle {

	protected ChainLink upLink = null;

	protected ChainLink downLink = null;

	protected DPoint3 gravity = new DPoint3(0, 1.0, 0);

	protected DPoint3 stiffness = new DPoint3(0.2, 0.2, 0.2);

	protected DPoint3 damping = new DPoint3(0.7, 0.7, 0.7);


	public ChainLink(DPoint3 pos, double mass, DPoint3 gravity, DPoint3 stiffness, DPoint3 damping) {
		super(pos);
		this.mass = mass;
		this.gravity = gravity;
		this.stiffness = stiffness;
		this.damping = damping;
	}


	public void update(double time, double dt) {
		super.update(time, dt);

		if (getUpLink() != null) {
			DPoint3 ref = getUpLink().getPosition();
			DPoint3 vel = getVelocity();

//			DPoint3 dpt = new DPoint3(dt, dt, dt);
//			DPoint3 dpos = ref.copy().sub(position).mul(dpt);
//			DPoint3 dforce = dpos.copy().mul(stiffness).add(gravity).scale(1.0 / mass).mul(damping);
//			vel.add(dforce);

			double dx = ref.getX() - position.getX();
			double forceX = dx * stiffness.getX();
			forceX += gravity.getX();
			double ax = dt * forceX / mass;
			vel.p[0] = damping.getX() * (vel.p[0] + ax);

			double dy = ref.getY() - position.getY();
			double forceY = dy * stiffness.getY();
			forceY += gravity.getY();
			double ay = dt * forceY / mass;
			vel.p[1] = damping.getY() * (vel.p[1] + ay);

			double dz = ref.getZ() - position.getZ();
			double forceZ = dz * stiffness.getZ();
			forceZ += gravity.getZ();
			double az = dt * forceZ / mass;
			vel.p[2] = damping.getZ() * (vel.p[2] + az);

			this.position.add(vel);
		}
	}


	public Chain getChain() {
		if (upLink != null) {
			return upLink.getChain();
		}
		return (Chain) this;
	}


	public ChainLink getUpLink() {
		return upLink;
	}


	public void setUpLink(ChainLink upLink) {
		this.upLink = upLink;
	}


	public ChainLink getDownLink() {
		return downLink;
	}


	public void setDownLink(ChainLink downLink) {
		this.downLink = downLink;
	}


	public DPoint3 getGravity() {
		return gravity;
	}


	public void setGravity(DPoint3 gravity) {
		this.gravity = gravity;
	}


	public DPoint3 getStiffness() {
		return stiffness;
	}


	public void setStiffness(DPoint3 stiffness) {
		this.stiffness = stiffness;
	}


	public DPoint3 getDamping() {
		return damping;
	}


	public void setDamping(DPoint3 damping) {
		this.damping = damping;
	}
}
